﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using ElectronicCommerce.Framework.Web.Configuration;
using ElectronicCommerce.Framework.Web.Configuration.Resource;

namespace ElectronicCommerce.Framework.Web.UI
{
    public class PageHead
    {
        private PageHeadMetaCollection httpEquivMetas = null;
        private PageHeadMetaCollection nameMetas = null;
        private List<CssItem> cssFiles = null;
        private List<CssItem> cssInlines = null;
        private List<JavascriptItem> javascriptFiles = null;
        private List<JavascriptItem> javascriptInlines = null;

        public PageHead()
        {
            Metas = new PageHeadMetaCollection();
            CssList = new List<CssItem>();
            JavascriptList = new List<JavascriptItem>();
            RssFeedList = new List<RssFeedItem>();
        }

        public string Title { get; set; }

        public string Icon { get; set; }

        public string ExtendContent { get; set; }

        public PageHeadMetaCollection Metas { get; private set; }

        public List<CssItem> CssList { get; private set; }

        public List<JavascriptItem> JavascriptList { get; private set; }

        public List<RssFeedItem> RssFeedList { get; private set; }

        #region Helper Method

        #region Meta

        public void AddHttpEquivMeta(string name, string content)
        {
            Metas.Add(new PageHeadMetaInfo(PageHeadMetaType.HttpEquiv, name, content));
        }

        public void AddNameMeta(string name, string content)
        {
            Metas.Add(new PageHeadMetaInfo(PageHeadMetaType.Name, name, content));
        }

        public PageHeadMetaCollection GetHttpEquivMetas()
        {
            EnsureMetaSplited();
            return httpEquivMetas;
        }

        public PageHeadMetaCollection GetNameMetas()
        {
            EnsureMetaSplited();
            return nameMetas;
        }

        private void EnsureMetaSplited()
        {
            if (httpEquivMetas == null || nameMetas == null)
            {
                httpEquivMetas = new PageHeadMetaCollection();
                nameMetas = new PageHeadMetaCollection();
                foreach (PageHeadMetaInfo metaInfo in Metas)
                {
                    if (metaInfo.Type == PageHeadMetaType.HttpEquiv)
                    {
                        httpEquivMetas.Add(metaInfo);
                    }
                    else if (metaInfo.Type == PageHeadMetaType.Name)
                    {
                        //httpEquivMetas.Add(metaInfo);
                        nameMetas.Add(metaInfo);
                    }
                }
            }
        }

        #endregion

        #region Style

        public void AddCssFile(Enum cssAlias)
        {
            AddCssFile(cssAlias, ConditionalCommentType.None, 0);
        }

        public void AddCssFile(Enum cssAlias, ConditionalCommentType conditionalCommentType, float browserVersion)
        {
            Css css = ConfigHelper.CssConfig.GetCss(cssAlias.ToString());
            AddCssFile(css.FileName, conditionalCommentType, browserVersion);
        }

        public void AddCssFile(string cssFile)
        {
            AddCssFile(cssFile, ConditionalCommentType.None, 0);
        }

        public void AddCssFile(string cssFile, ConditionalCommentType conditionalCommentType, float browserVersion)
        {
            AddCssItem(CssType.External, cssFile, conditionalCommentType, browserVersion);
        }

        public void AddInlineStyle(string content)
        {
            AddInlineStyle(content, ConditionalCommentType.None, 0);
        }

        public void AddInlineStyle(string content, ConditionalCommentType conditionalCommentType, float browserVersion)
        {
            AddCssItem(CssType.Inline, content, conditionalCommentType, browserVersion);
        }

        public virtual void AddCssItem(CssType styleType, string content, ConditionalCommentType conditionalCommentType, float browserVersion)
        {
            CssItem styleItem = new CssItem();
            styleItem.Type = styleType;
            styleItem.Content = content;
            styleItem.ConditionalCommentType = conditionalCommentType;
            styleItem.BrowserVersion = browserVersion;
            if (!CssList.Contains(styleItem))
            {
                CssList.Add(styleItem);
            }
        }

        public List<CssItem> GetCssFiles()
        {
            EnsureStyleSplited();
            return cssFiles;
        }

        public List<CssItem> GetInlineStyles()
        {
            EnsureStyleSplited();
            return cssInlines;
        }

        public void EnsureStyleSplited()
        {
            if (cssFiles == null || cssInlines == null)
            {
                cssFiles = new List<CssItem>();
                cssInlines = new List<CssItem>();

                foreach (CssItem styleItem in CssList)
                {
                    if (styleItem.Type == CssType.External)
                    {
                        cssFiles.Add(styleItem);
                    }
                    else if (styleItem.Type == CssType.Inline)
                    {
                        cssInlines.Add(styleItem);
                    }
                }
            }
        }

        #endregion

        #region Javascript

        public void AddJavascriptFile(Enum jsAlias)
        {
            Javascript js = ConfigHelper.JavascriptConfig.GetJavascript(jsAlias.ToString());
            AddJavascriptFile(js.FileName);
        }

        public void AddJavascriptFile(Enum jsAlias, string param)
        {
            Javascript js = ConfigHelper.JavascriptConfig.GetJavascript(jsAlias.ToString());
            AddJavascriptFile(js.FileName + "?" + param);
        }

        public void AddJavascriptFile(string javascriptFile)
        {
            AddJavascriptItem(JavascriptType.External, javascriptFile);
        }

        public void AddInlineJavascript(string content)
        {
            AddJavascriptItem(JavascriptType.Inline, content);
        }

        public virtual void AddJavascriptItem(JavascriptType javascriptType, string content)
        {
            JavascriptItem javascriptItem = new JavascriptItem();
            javascriptItem.Type = javascriptType;
            javascriptItem.Content = content;
            if (!JavascriptList.Contains(javascriptItem))
            {
                JavascriptList.Add(javascriptItem);
            }
        }

        public List<JavascriptItem> GetJavascriptFiles()
        {
            EnsureJavascriptSplited();
            return javascriptFiles;
        }

        public List<JavascriptItem> GetInlineJavascripts()
        {
            EnsureJavascriptSplited();
            return javascriptInlines;
        }

        private void EnsureJavascriptSplited()
        {
            if (javascriptFiles == null || javascriptInlines == null)
            {
                javascriptFiles = new List<JavascriptItem>();
                javascriptInlines = new List<JavascriptItem>();
                foreach (JavascriptItem javascriptItem in JavascriptList)
                {
                    if (javascriptItem.Type == JavascriptType.Inline)
                    {
                        javascriptInlines.Add(javascriptItem);
                    }
                    else if (javascriptItem.Type == JavascriptType.External)
                    {
                        javascriptFiles.Add(javascriptItem);
                    }
                    else if (javascriptItem.Type == JavascriptType.ExternalOtherWeb)
                    {
                        javascriptFiles.Add(javascriptItem);
                    }
                }
            }
        }

        #endregion

        #region RssFeed

        public void AddRssFeed(string title, string url)
        {
            RssFeedItem rssFeedItem = new RssFeedItem();
            rssFeedItem.Title = title;
            rssFeedItem.Url = url;
            RssFeedList.Add(rssFeedItem);
        }

        #endregion

        #endregion
    }

    #region Page Head MetaInfo

    public class PageHeadMetaInfo
    {
        public PageHeadMetaInfo(PageHeadMetaType type, string name, string content)
        {
            Type = type;
            Name = name;
            Content = content;
        }

        public PageHeadMetaType Type { get; set; }
        public string Name { get; set; }
        public string Content { get; set; }
    }

    public enum PageHeadMetaType
    {
        HttpEquiv,
        Name
    }

    public class PageHeadMetaCollection : KeyedCollection<string, PageHeadMetaInfo>
    {

        protected override string GetKeyForItem(PageHeadMetaInfo item)
        {
            return item.Name;
        }
    }

    #endregion

    #region Style

    public struct CssItem
    {
        public string Content;
        public CssType Type;
        public ConditionalCommentType ConditionalCommentType;
        public float BrowserVersion;
    }

    public enum CssType
    {
        Inline,
        External
    }

    public enum ConditionalCommentType
    {
        None,

        NonIEOnly,
        IEOnly,
    }

    #endregion

    #region Javascript

    public struct JavascriptItem
    {
        public string Content;
        public JavascriptType Type;
    }

    public enum JavascriptType
    {
        Inline,
        External,
        ExternalOtherWeb
    }

    #endregion

    #region Rss

    public struct RssFeedItem
    {
        public string Title;
        public string Url;
    }

    #endregion
}
